package org.wheel.plugins.toolkit.sql.segment;

import cn.hutool.core.lang.Pair;
import lombok.Getter;
import org.wheel.plugins.toolkit.sql.core.SqlSegment;
import org.wheel.plugins.toolkit.sql.core.AbstractWrapper;
import org.wheel.plugins.toolkit.sql.core.WrapperContext;
import org.wheel.plugins.toolkit.sql.entity.AliasEntry;
import org.wheel.plugins.toolkit.sql.enums.SqlModel;
import org.wheel.plugins.toolkit.sql.helper.AliasRegistry;
import org.wheel.plugins.toolkit.sql.helper.ParamBank;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * 子查询片段 – 延时渲染版
 * 负责：参数重编号 + SQL 占位符替换 + 表别名重编号
 */
public final class SubQuerySegment implements SqlSegment {

    private final AbstractWrapper<?, ?> subWrapper;   // 子查询 Wrapper（含独立上下文）
    private final AbstractWrapper<?, ?> parentWrapper; // 父查询 Wrapper（含独立上下文）
    private String sql;                            // 重编号后的 SQL 缓存
    @Getter
    private LinkedHashMap<String, Object> paramMap;

    private LinkedHashMap<String, Object> oldParamMap;

    public SubQuerySegment(AbstractWrapper<?, ?> subWrapper, AbstractWrapper<?, ?> parentWrapper) {
        this.subWrapper = subWrapper;
        this.oldParamMap = subWrapper.getContext().getParamBank().toMap();
        this.parentWrapper = parentWrapper;
        mergeParameters();
    }

    @Override
    public String getSql() {

        return sql;
    }


    /**
     * 1. 子查询参数重编号 & SQL 占位符替换
     * 2. 表别名重编号 + SQL 别名替换
     * @param subQuery 子查询
     * @param mainBank 主查询参数
     * @return [新SQL, 新参数Map]
     */
    /**
     * 子查询「参数 + 表别名」双重重编号
     * 返回 [新SQL, 新参数Map]
     */
    private Pair<String, LinkedHashMap<String, Object>> mergeParameters() {

        ParamBank mainBank = this.parentWrapper.getContext().getParamBank();
        AliasRegistry mainAliasReg = this.parentWrapper.getContext().getAliasRegistry();
        /* ---------- 1. 参数重编号 ---------- */
        Map<String, Object> oldParam = this.subWrapper.getContext().getParamBank().toMap();
        LinkedHashMap<String, Object> newParam = new LinkedHashMap<>();
        String sql = this.subWrapper.getSql();

        /* 参数替换 */
        for (Map.Entry<String, Object> e : oldParam.entrySet()) {
            String newKey = mainBank.nextParam(e.getValue());
            newParam.put(newKey, e.getValue());
            // 需要依据子查询的SQL模式，找到正确的占位符
            String sourceKey = randerKey(this.subWrapper.getSqlModel(), e.getKey());
            String targetVal = randerKey(this.parentWrapper.getSqlModel(), newKey);
            sql = sql.replace(sourceKey, targetVal);
        }

        /* ---------- 2. 表别名重编号 ---------- */
        LinkedHashMap<String, String> aliasRemap = new LinkedHashMap<>();
        for (Map.Entry<Class<?>, List<AliasEntry>> e : this.subWrapper.getContext().getAliasRegistry().getEntityAliases().entrySet()) {
            for (AliasEntry ae : e.getValue()) {
                String oldAlias = ae.getAlias();
                String newAlias = mainAliasReg.nextAlias();   // 全局连续
                aliasRemap.put(oldAlias, newAlias);
                // 更新到主注册表（可选，看你是否需要后续解析）
                mainAliasReg.register(e.getKey(), newAlias);
            }
        }
        /* 替换 SQL 里的别名 */
        for (Map.Entry<String, String> e : aliasRemap.entrySet()) {
            sql = sql.replace(" " + e.getKey() + ".", " " + e.getValue() + ".")   // t1.id -> t2.id
                    .replace(" AS " + e.getKey(), " AS " + e.getValue());        // xxx AS t1 -> xxx AS t2
        }

        this.sql = sql;
        this.paramMap = this.parentWrapper.getContext().getParamBank().toMap();

        return Pair.of(sql, newParam);
    }

    private String randerKey(SqlModel model, String key) {
        return model.render(key);
    }
}